﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.NetworkAnalyst;
using ESRI.ArcGIS.Geometry;
using System.IO;
using System.Windows.Forms;
using ESRI.ArcGIS.DataSourcesGDB;


namespace Arcgis
{
    class RouteClass
    {
        private const String FGDB_WORKSPACE = @"D:\MyGIS\sj\新建文件夹\新建文件地理数据库.gdb";
        private const String FEATURE_DATASET = "road";
        private const String NETWORK_DATASET = "road_ND";
        private const String POINT_DATASET = "stops";
        // 添加起点终点字段

        private IFeatureLayer m_routeLayer;

        // 获取结果图层
        public IFeatureLayer GetRouteLayer() => m_routeLayer;
        // 添加调试方法
        public string GetDebugInfo()
        {
            string docPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            string fullPath = System.IO.Path.Combine(docPath, FGDB_WORKSPACE);

            return $"工作空间路径: {fullPath}\n" +
                   $"要素数据集: {FEATURE_DATASET}\n" +
                   $"网络数据集: {NETWORK_DATASET}";
        }

        

        public void easySolveRoute(IPoint m_startPoint, IPoint m_endPoint)
        {
            try
            {
                //1. 打开工作空间
                IWorkspaceFactory workspaceFactory = Activator.CreateInstance(
                    Type.GetTypeFromProgID("esriDataSourcesGDB.FileGDBWorkspaceFactory")) as IWorkspaceFactory;

                string fullPath = System.IO.Path.Combine(
                    Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                    FGDB_WORKSPACE);

                IFeatureWorkspace featureWorkspace = workspaceFactory.OpenFromFile(fullPath, 0) as IFeatureWorkspace;

                // 2. 获取网络数据集 - 直接打开，不再使用"Stores"
                IFeatureDataset featureDataset = featureWorkspace.OpenFeatureDataset(FEATURE_DATASET);
                IFeatureDataset stopsfeatureDataset = featureWorkspace.OpenFeatureDataset(POINT_DATASET);
                IFeatureDatasetExtensionContainer featureDatasetExtensionContainer =
                    featureDataset as IFeatureDatasetExtensionContainer;

                IFeatureDatasetExtension featureDatasetExtension = featureDatasetExtensionContainer.FindExtension(esriDatasetType.esriDTNetworkDataset);

                IDatasetContainer3 datasetContainer3 = featureDatasetExtension as IDatasetContainer3;
                //3. 创建路径分析图层
                ESRI.ArcGIS.Geodatabase.IDataset dataset = datasetContainer3.get_DatasetByName(ESRI.ArcGIS.Geodatabase.esriDatasetType.esriDTNetworkDataset, NETWORK_DATASET);
                INetworkDataset networkDataset = dataset as INetworkDataset;
                //4. 配置分析环境
                INALayer naLayer = CreateRouteAnalysisLayer("Route", networkDataset);
                INAContext naContext = naLayer.Context;
                //5. 加载停靠点数据
                INAClassFieldMap naClassFieldMap = (INAClassFieldMap)stopsfeatureDataset;
                ITable stopTable = naClassFieldMap as ITable;

                // 添加起点
                IRow startStop1 = CreateStopRow(stopTable, m_startPoint, "起点",1);
                startStop1.Store();

                // 添加终点
                IRow endStop1 = CreateStopRow(stopTable, m_endPoint, "终点",2);
                endStop1.Store();

                IRow row = (IRow)stopsfeatureDataset;
                row.Equals(startStop1);
                row.Equals(endStop1);
                stopsfeatureDataset = (IFeatureDataset)row;

                INAClass stopsNAClass = naContext.NAClasses.get_ItemByName("Stops") as INAClass;
                ITable stopsTable = stopsNAClass as ITable;
                // 从点数据集中获取所有点要素
                IFeatureClass pointFeatureClass = featureWorkspace.OpenFeatureClass(POINT_DATASET);
                IFeatureCursor pointCursor = pointFeatureClass.Search(null, false);
                IFeature pointFeature = pointCursor.NextFeature();

                int sequence = 1;
                while (pointFeature != null)
                {
                    // 添加点作为停靠点
                    IRow stopRow = CreateStopRow(stopsTable, pointFeature.ShapeCopy as IPoint,
                                                pointFeature.OID.ToString(), sequence);
                    if (stopRow != null)
                    {
                        stopRow.Store();
                        sequence++;
                    }
                    pointFeature = pointCursor.NextFeature();
                }

                // 确保释放游标
                System.Runtime.InteropServices.Marshal.ReleaseComObject(pointCursor);

                // 添加起点（如果不在点数据集中）
                IRow startStop = CreateStopRow(stopsTable, m_startPoint, "起点", 0);
                if (startStop != null)
                {
                    startStop.Store();
                }

                // 添加终点（如果不在点数据集中）
                IRow endStop = CreateStopRow(stopsTable, m_endPoint, "终点", sequence);
                if (endStop != null)
                {
                    endStop.Store();
                }

                // 更新分析上下文
                INAContextEdit naContextEdit = naContext as INAContextEdit;
                naContextEdit.ContextChanged();

                // 添加定位器设置
                INALocator3 locator = naContext.Locator as INALocator3;
                locator.ExcludeRestrictedElements = true;
                locator.CacheRestrictedElements(naContext);



                //6. 执行路径分析
                INASolver naSolver = naContext.Solver;
                naSolver.Solve(naContext, new GPMessagesClass(), new CancelTrackerClass());

                //7. 获取结果图层
                IFeatureClass routesFC = naContext.NAClasses.get_ItemByName("Routes") as IFeatureClass;
                // 保存结果
                SaveLayerToDisk(naLayer as ILayer, System.Environment.CurrentDirectory + @"\Route.lyr");

                // 7. 获取结果图层（新增）
                m_routeLayer = new FeatureLayerClass();
                m_routeLayer.FeatureClass = routesFC;
                m_routeLayer.Name = "最短路径结果";

                // 设置路径显示样式（红色线）
                ISimpleLineSymbol lineSymbol = new SimpleLineSymbolClass();
                lineSymbol.Color = GetColor(255, 0, 0); // 红色
                lineSymbol.Width = 3;
                lineSymbol.Style = esriSimpleLineStyle.esriSLSSolid;

                ISimpleRenderer renderer = new SimpleRendererClass();
                renderer.Symbol = lineSymbol as ISymbol;

                IGeoFeatureLayer geoLayer = m_routeLayer as IGeoFeatureLayer;
                geoLayer.Renderer = renderer as IFeatureRenderer;
            }

            catch (Exception ex)
            {
                // 添加详细错误信息
                throw new Exception($"路径分析失败: {ex.Message}\n\n{GetDebugInfo()}");
            }
        }

        private INALayer CreateRouteAnalysisLayer(String layerName, INetworkDataset networkDataset)
        {
            INARouteSolver naRouteSolver = new NARouteSolverClass();
            INASolverSettings naSolverSettings = naRouteSolver as INASolverSettings;
            INASolver naSolver = naRouteSolver as INASolver;

            IDatasetComponent datasetComponent = networkDataset as IDatasetComponent;
            IDENetworkDataset deNetworkDataset = datasetComponent.DataElement as IDENetworkDataset;

            INAContext naContext;
            naContext = naSolver.CreateContext(deNetworkDataset, layerName);
            INAContextEdit naContextEdit = naContext as INAContextEdit;
            naContextEdit.Bind(networkDataset, new GPMessagesClass());

            INALayer naLayer;
            naLayer = naSolver.CreateLayer(naContext);
            (naLayer as ILayer).Name = layerName;

            naRouteSolver.FindBestSequence = true;
            naRouteSolver.PreserveFirstStop = true;
            naRouteSolver.PreserveLastStop = false;
            naRouteSolver.UseTimeWindows = false;
            naRouteSolver.OutputLines = esriNAOutputLineType.esriNAOutputLineTrueShapeWithMeasure;

            IStringArray restrictions = naSolverSettings.RestrictionAttributeNames;
            restrictions.Add("Oneway");
            naSolverSettings.RestrictionAttributeNames = restrictions;

            naSolver.UpdateContext(naContext, deNetworkDataset, new GPMessagesClass());

            return naLayer;
        }

        private void SaveLayerToDisk(ILayer layer, String path)
        {
            try
            {
                Console.WriteLine("Writing layer file containing analysis to " + path);
                ILayerFile layerFile = new LayerFileClass();
                layerFile.New(path);
                layerFile.ReplaceContents(layer as ILayer);
                layerFile.Save();
                Console.WriteLine("Writing layer file successfully saved");
            }
            catch (Exception err)
            {
                // Write out errors
                Console.WriteLine(err.Message);
            }
        }
        private IRow CreateStopRow(ITable table, IPoint point, string name, int sequence)
        {
            IRow row = table.CreateRow();
            row.set_Value(table.FindField("Shape"), point);
            row.set_Value(table.FindField("Name"), name);

            int seqField = table.FindField("Sequence");
            if (seqField > -1) row.set_Value(seqField, sequence);

            return row;
        }

        private IRow CreateStopRow(ITable table, IPoint point, string name)
        {
            
            IRow row = table.CreateRow();

            // 仅设置存在的字段
            int shapeField = table.FindField("Shape");
            if (shapeField >= 0) row.set_Value(shapeField, point);

            int nameField = table.FindField("Name");
            if (nameField >= 0) row.set_Value(nameField, name);

            // 不再设置Sequence字段
            return row;
        }


        private IRgbColor GetColor(int r, int g, int b)
        {
            IRgbColor color = new RgbColorClass();
            color.Red = r;
            color.Green = g;
            color.Blue = b;
            return color;
        }
    }
}
